﻿#include <metaconstructor.h>

#include "RXNode.h"
#include "RXEntity.h"
#include "RXWorld.h"
#include "RXComponent.h"


BeginMetaData(RXNode)

META_BEGIN_CONSTRUCTOR(RXNodeCreationInfo*)
META_END_CONSTRUCTOR

META_BEGIN_PROPERTY(HeaderNode)
META_ADD_GETTER(GetHeaderNode)
META_END_PROPERTY

META_BEGIN_PROPERTY(Enabled)
META_ADD_GETTER(IsEnabled)
META_ADD_SETTER(SetEnabled)
META_ADD_NOTIFIER(EnableChanged)
META_END_PROPERTY

META_BEGIN_SIGNAL(EnableChanged)
META_END_SIGNAL

EndMetaData

RXNode::RXNode(RXNodeCreationInfo* info):m_enable(true)
{
	this->m_world = info->world;
	this->m_id = info->nodeid;
	this->m_header = info->header;
}

RXNode::~RXNode()
{
	if (m_world) {
		m_world->UnRegisterNode(this);
	}
}

void RXNode::SetParent(RXTree * node)
{
	RXNode * other = dynamic_cast<RXNode*>(node);
	bool isOtherNull = (node == NULL);
	bool isOtherDerivedOfRXNode = dynamic_cast<RXNode*>(node);
	bool isThisEntity = dynamic_cast<RXEntity*>(this);

	bool isThisComponent = dynamic_cast<RXComponent*>(this);

	bool isOtherEntity = dynamic_cast<RXEntity*>(node);

	bool isOtherComponent = dynamic_cast<RXComponent*>(node);

	if (!isOtherNull && !isOtherDerivedOfRXNode) {
		std::cerr << "RXNode::SetParent失败，父级必须是RXNode的子类" << std::endl;
		assert(false);
		return;
	}

	if (isThisEntity && isOtherComponent) {
		if (FindChild<RXComponent>({}, false)) {
			std::cerr << "RXNode::SetParent失败，一个实体下只能有一个组件。" << std::endl;
			assert(false);
			return;
		}
	}

	if (isThisEntity && !isOtherNull && !isOtherEntity) {
		std::cerr << "RXNode::SetParent失败，一个实体的父级必然是实体" << std::endl;
		assert(false);
		return;
	}

	RXWorld * thisWorld = m_world;
	RXWorld* otherWorld = other ? other->m_world : NULL;

	if (thisWorld != otherWorld) {
		std::cerr << "RXNode::SetParent失败，你不可以把一个Wolrd下的节点移动到另一个World里" << std::endl;
		assert(false);
		return;
	}

	RXTree::SetParent(node);
}

RXECSDef::NodeId RXNode::GetNodeId() const
{
	return m_id;
}

RXWorld * RXNode::GetWorld()
{
	return m_world;
}

bool RXNode::IsEnabled() const
{
	return m_enable;
}

void RXNode::SetEnabled(bool v)
{
	if (v != m_enable)
	{
		m_enable = v;
		EnableChanged(v);
	}
}

bool RXNode::IsGlobalEnabled() const
{
	auto p = this;
	while (p)
	{

		if (!p->IsEnabled()) {
			return false;
		}

		p = dynamic_cast<RXNode*>(p->GetParent());
	}

	return true;
}

RXECSDef::NodeId RXNode::GetHeaderNode() const
{
	return m_header;
}

const std::wstring RXNode::GetCreateName() const
{
	return m_creatName;
}

void RXNode::PostEventToShadowNode(ThreadSafe::Event * e)
{
	if (m_world) {
		m_world->PostEventToShadowNode(this, e);
	}
}

RXNode * RXNode::CreateDefaultSubObjectImp(RXNode * parent, const wchar_t * objectName, MetaInfo meta)
{
	if (FindChild<RXNode>(objectName, true))
	{
		std::cerr << "RXNode::CreateDefaultSubObject: 默认子节点不可以重名" << std::endl;
		assert(false);
	}

	int index = meta.IndexOfConstructor({MetaType::IdFromType<RXNodeCreationInfo*>()});

	if (index == -1)
	{
		return  NULL;
	}

	auto mc = meta.GetConstructor(index);

	RXNodeCreationInfo info;
	info.header = m_header;
	info.nodeid = m_world->AllocNodeId();
	info.world = m_world;

	void* tempret = mc.Create(NULL, &info);
	RXNode* ret = meta.MetaCast<RXNode>(tempret);

	if (parent == NULL)
	{
		parent = this;
	}

	ret->SetParent(parent);
	ret->SetName(objectName);
	ret->m_creatName = objectName;

	return ret;
}
